package Soligee.model.persistencia;
//orc
import Soligee.model.vo.cadastros.UsuarioVO;
import Soligee.hibernate.HibernateUtil;
import org.hibernate.criterion.*;
import org.hibernate.*;
import org.hibernate.SQLQuery.*;
import java.util.*;
import org.hibernate.exception.ConstraintViolationException;

public class DAO {

    private Session session = null;
    private final Class classe;
    private Transaction tx;

    public DAO(Class classe) {
        this.setSession(HibernateUtil.getInstance());
        this.classe = classe;
        this.tx = null;
        this.session.flush();
    }

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }

    public boolean Incluir(Object objeto) throws Exception{              
        try {
            tx = getSession().beginTransaction();
            getSession().save(objeto);
            tx.commit();
            return true;
        }catch(ConstraintViolationException c){
            System.err.println("Erro: campos duplicados ou nulos - "+ c.getMessage());
            tx.rollback();
            throw new Exception(c.getMessage(),c);
        } catch (Exception e) {
            System.err.println("Erro:" + e.getMessage());
            tx.rollback();
            System.err.println(e.getStackTrace());
            throw new Exception(e.getMessage(),e);
        }//fim catch
        finally {
            this.getSession().close();
        }
    }//fim incluir

    public boolean Excluir(Object objeto)throws Exception {
           try {
            tx = getSession().beginTransaction();
            getSession().delete(objeto);
            tx.commit();         
            return true;
        } catch (Exception e) {
            System.err.println("Erro:" + e.getMessage());
            tx.rollback();
            throw new Exception(e.getMessage(),e);
        }//fim catch
        finally {
            this.getSession().close();
        }
    }//fim excluir

    public boolean update(Object objeto) throws Exception {
        try {
            tx = getSession().beginTransaction();
            getSession().merge(objeto);           
            tx.commit();          
            return true;
         }catch (org.hibernate.StaleStateException ex) {
            tx.rollback();
            throw new Exception(ex.getMessage(),ex);
        } catch (Exception e) {
            System.err.println("Erro:" + e.getMessage());
            tx.rollback();
            throw new Exception(e.getMessage(),e);
        }//fim catch
        finally {
            this.getSession().close();
        }
    }//fim update
    //busca para efetuar o login

    public boolean buscaPeloLoginSenha(String login, String senha) {
        int aux = 0;
        try {
            Criteria select = getSession().createCriteria(this.classe);
            select.add(Restrictions.ilike("login", login, MatchMode.EXACT));
            select.add(Restrictions.ilike("senha", senha, MatchMode.EXACT));
            List consulta = select.list();
            Iterator iterador = consulta.iterator();
            if (consulta.isEmpty() == true) {
                aux = 0;
            } else {
                UsuarioVO usuario = (UsuarioVO) iterador.next();
                if ((usuario.getLogin().equalsIgnoreCase(login) == true) && (usuario.getSenha().equals(senha) == true)) {
                    aux = 1;
                }//fim if
            }//fim else
        }catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return false;
        } catch (Exception e) {
            System.err.println("Ocorreu um erro:" + e.getMessage());
        }//fim catch
        finally {
            if (aux == 1) {
                return true;
            } else {
                return false;
            }
        }//fim finally
    }//fim metodo

    public List buscaNome(CriterioBusca criterios) {
        //em ordem crescente do criterio
        try {
            this.setSession(HibernateUtil.getInstance());
            Criteria busca = getSession().createCriteria(this.classe);
            busca.add(Restrictions.ilike(criterios.getCriterioBusca(), criterios.getValor().toString(), MatchMode.START))
                    .add(Restrictions.eq("ativo", true));
            busca.addOrder(Order.asc(criterios.getCriterioBusca()));
            return busca.list();
       } catch (NullPointerException ex) {
         System.err.println("Ocorreu um erro" + ex.getMessage());
         return null;
        } catch(Exception e) {
            System.err.println("Ocorreu um erro:" + e.getMessage());
            return null;
        }finally {
            //this.getSession().close();
        }
    }//fim busca


    public List buscaComPaginacao(CriterioBusca criterios, int firstResult, int maxResult) {
        //em ordem crescente do criterio
        try {
            Criteria busca = getSession().createCriteria(this.classe);
            busca.add(Restrictions.ilike(criterios.getCriterioBusca(), criterios.getValor().toString())).add(Restrictions.eq("ativo", true));
            busca.addOrder(Order.asc(criterios.getCriterioBusca())).setFirstResult(firstResult).setMaxResults(maxResult);
            return busca.list();
        } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
        } catch (Exception e) {
            System.err.println("Ocorreu um erro:" + e.getMessage());
            return null;
        }finally {
            this.getSession().close();
        }
    }//fim busca

    //busca todos registros com ordenacao determinada pelo usuario
    public List buscarTodos(String ordenarPor) {
      try{
        List t = this.getSession().createCriteria(this.classe)
                .add(Restrictions.eq("ativo", true)) //filtra: apenas os ativos
                .addOrder(Order.asc(ordenarPor)).list();//ordena a lista
        return t;
      } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
      }catch(Exception e){
           System.err.println("Ocorreu um erro" + e.getMessage());
             return null;
      }finally{
            //this.getSession().close();
      }
    }//fim lista tudo

    public List buscarTodosComInativos(String ordenarPor) {
      try{
        List t = this.getSession().createCriteria(this.classe)
                .addOrder(Order.asc(ordenarPor)).list();//ordena a lista
        return t;
      } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
      }catch(Exception e){
           System.err.println("Ocorreu um erro" + e.getMessage());
             return null;
      }finally{
            //this.getSession().close();
      }
    }//fim lista tudo


     //busca todos registros com ordenacao determinada pelo usuario
    public List buscarTodosComAssociacao(String nomeObjetoAssociado,CriterioBusca criterios,String ordenarPor) {
      try{
        List t = this.getSession().createCriteria(this.classe).addOrder(Order.asc(ordenarPor))
                .createCriteria(nomeObjetoAssociado).add(Restrictions.eq(criterios.getCriterioBusca(),criterios.getValor()))
                .list();
        return t;
      } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
      }catch(Exception e){
           System.err.println("Ocorreu um erro" + e.getMessage());
             return null;
      }finally{
            //this.getSession().close();
      }
    }//fim lista tudo

    //pagina sem criterio
    public List buscarTodosComPaginacao(int firstResult, int maxResult,String ordenarPor) {
       try{
        List t = this.getSession().createCriteria(this.classe)
                .setFirstResult(firstResult).setMaxResults(maxResult)
                 .add(Restrictions.eq("ativo", true))
                 .addOrder(Order.asc(ordenarPor)).list();
        return t;
       } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
       }catch(Exception e){
         System.out.println("Erro na busca com paginação: "+e.getMessage()+ e.getStackTrace());
         return null;
       }finally {
           this.getSession().close(); }
    }//fim lista tudo


   //pagina com criterio, ou seja, com uma clausula where
   public List buscarTodosComPaginacaoComCriterio(int firstResult, int maxResult,String ordenarPor,CriterioBusca criterio) {
       try{
        List t = this.getSession().createCriteria(this.classe).add(Restrictions.ilike(criterio.getCriterioBusca(),"%"+criterio.getValor()+"%"))
                .setFirstResult(firstResult).setMaxResults(maxResult)
                 .add(Restrictions.eq("ativo", true))
                 .addOrder(Order.asc(ordenarPor)).list();
        return t;
       } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
       }catch(Exception e){
         System.out.println("Erro na busca com paginação: "+e.getMessage()+ e.getStackTrace());
         return null;
       }finally {
           this.getSession().close(); }
    }//fim lista tudo

    //busca com projection e devolve o total de registros(linhas)
    public List buscarCodigo(CriterioBusca criterios) {
        try {
            Criteria busca = getSession().createCriteria(this.classe)
                    .add(Restrictions.eq(criterios.getCriterioBusca(), criterios.getValor()))
                     .add(Restrictions.eq("ativo", true));
            List it = busca.list();
            return it;
        } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
        } catch (Exception e) {
            System.err.println("Ocorreu um erro:" + e.getMessage());
            return null;
        }finally{
           this.getSession().close();
        }
    }//busca funcionando por codido

    public List buscarInteiro(String coluna, int codigo) {
        try {
            Criteria busca = getSession().createCriteria(this.classe)
                    .add(Restrictions.eq(coluna, codigo))
                     .add(Restrictions.eq("ativo", true));
            List it = busca.list();
            return it;
        } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
        } catch (Exception e) {
            System.err.println("Ocorreu um erro:" + e.getMessage());
            return null;
        }finally{
           this.getSession().close();
        }
    }

    public int buscaTotalRegistros() {
      try{
        int valorRetorno = 0;
        Criteria busca = getSession().createCriteria(this.classe).setProjection(Projections.rowCount());
        List lista = busca.list();
        if(lista.isEmpty()){
            valorRetorno = 0;
        }else{
         Iterator aux = busca.list().iterator();
         valorRetorno = Integer.parseInt(aux.next().toString());
       }//fim else
        return valorRetorno;
      } catch (NullPointerException ex) {
         System.err.println("Ocorreu um erro" + ex.getMessage());
         return 0;
      }catch(Exception e){
          System.err.println("Ocorreu um erro:" + e.getMessage());
          return 0;
      }finally {
            this.getSession().close();
        }
    }//busca funcionando = total de registros(rows)

    //criterio de busca o item a ser feito o join
    public List buscaComAssociacao(CriterioBusca criterios, String nomeObjetoAssociado) {
       try {
         Criteria busca = getSession().createCriteria(this.classe).createCriteria(nomeObjetoAssociado)
                 .add(Restrictions.ilike(criterios.getCriterioBusca(),criterios.getValor().toString(), MatchMode.START))
                  .add(Restrictions.eq("ativo", true));
         return busca.list();
       } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro na busca com associação:" + ex.getMessage());
             return null;
        }catch (Exception e ){
            System.err.println("Erro na consulta. Excecao:" + e.getMessage());
            return null;
        } finally {
            this.getSession().close();
        }
    }//fim busca com associacao

    public List buscaComAssociacaoSemCriterio(String nomeObjetoAssociado){
        try {
         Criteria busca = getSession().createCriteria(this.classe).createCriteria(nomeObjetoAssociado)
                  .add(Restrictions.eq("ativo", true));
         return busca.list();
       } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro na busca com associação sem criterio:" + ex.getMessage());
             return null;
        }catch (Exception e ){
            System.err.println("Erro na consulta. Excecao:" + e.getMessage());
            return null;
        }finally {
            this.getSession().close();
        }
    }

    public List buscaComItem(String nomeObjetoAssociado){
       try {
            Criteria busca = getSession().createCriteria(this.classe).createCriteria("chaveComposta").
                   createCriteria(nomeObjetoAssociado);//.add(Restrictions.eq("ativo", true));
            return busca.list();
       }catch (Exception e ){
            System.err.println("Erro na consulta. Excecao:" + e.getMessage());
            return null;
        }finally {
            this.getSession().close();
        }
    }

    public List buscaComItemCriteriosa(CriterioBusca criterios,String nomeObjetoAssociado){
      try {
            Criteria busca = getSession().createCriteria(this.classe).createCriteria(nomeObjetoAssociado)
                    .add(Restrictions.eq(criterios.getCriterioBusca(),criterios.getValor()));
            return busca.list();
       }catch (Exception e ){
            System.err.println("Erro na consulta. Excecao:" + e.getMessage());
            return null;
        }finally {
            this.getSession().close();
        }
    }
    public List buscarParcelaPendente(String ordenarPor) {
      try{
        List t = this.getSession().createCriteria(this.classe)
                .add(Restrictions.eq("situacao", 0)) //filtra: apenas os ativos
                .addOrder(Order.asc(ordenarPor)).list();//ordena a lista
        return t;
      } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
      }catch(Exception e){
           System.err.println("Ocorreu um erro" + e.getMessage());
             return null;
      }finally{
            //this.getSession().close();
      }
    }
    //Buscar por data.
    public List buscarPorData(Date data, String ordenarPor) {
      try{
        List t = this.getSession().createCriteria(this.classe)
                .add(Restrictions.eq("dataLancamento", data)) //filtra: apenas os ativos
                .addOrder(Order.asc(ordenarPor)).list();//ordena a lista
        return t;
      } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
      }catch(Exception e){
           System.err.println("Ocorreu um erro" + e.getMessage());
             return null;
      }finally{
            //this.getSession().close();
      }
    }

    public List buscarPorDataGeral(Date data, String colunaDeData,String ordenarPor) {
      try{
        List t = this.getSession().createCriteria(this.classe)
                .add(Restrictions.eq(colunaDeData, data)) //filtra: apenas os ativos
                .addOrder(Order.asc(ordenarPor)).list();//ordena a lista
        return t;
      } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
      }catch(Exception e){
           System.err.println("Ocorreu um erro" + e.getMessage());
             return null;
      }finally{
            //this.getSession().close();
      }
    }

    public List buscarParcelaNF (Date data, String colunaDeData,String ordenarPor) {
      try{
        List t = this.getSession().createCriteria(this.classe)
                .add(Restrictions.eq(colunaDeData, data)).add(Restrictions.eq("situacao", 0)) //filtra: apenas os ativos
                .addOrder(Order.asc(ordenarPor)).list();//ordena a lista
        return t;
      } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
      }catch(Exception e){
           System.err.println("Ocorreu um erro" + e.getMessage());
             return null;
      }finally{
            //this.getSession().close();
      }
    }

    public double buscarSoma(Date data, String coluna_a_somar){
        try{
            Criteria criteria = this.getSession().createCriteria(this.classe).setProjection(Projections.sum(coluna_a_somar)).add(Restrictions.eq("dataLancamento", data));
            double resultado = Double.parseDouble(criteria.uniqueResult().toString());
            return resultado;
        }
        catch (NullPointerException ex) {
            System.err.println("Ocorreu um erro" + ex.getMessage());
            return 0;
        }catch(Exception e){
            System.err.println("Ocorreu um erro" + e.getMessage());
            return 0;
        }finally{
            this.getSession().close();
        }
    }



}//fim class